﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using Borg;
using Monitor;

[ParamValue("ExecuteInMainThread", true, new string[] { })]
[Plug("Startup")]
[Extension("Monitor", OnCreated = "OnCreated", OnReleased = "OnReleased")]
[Monitor(OnExtensionCreated = "ExtensionCreated", OnExtensionReleased = "ExtensionReleased")]
internal class PluginView : Form, IStartup
{
    private readonly Dictionary<ExtensionInfo, SlotButton> _slots =
        new Dictionary<ExtensionInfo, SlotButton>();

    private readonly SlotButton _dummy = new SlotButton();
    private readonly IContainer components = null;

    private readonly int _maxVisibleslots;

    public void Run()
    { }

    public void OnCreated(object sender, ExtensionEventArgs e)
    {
        Show();
    }

    public void OnReleased(object source, ExtensionEventArgs e)
    {
        Hide();
    }

    private void InitializeComponent()
    {
        SuspendLayout();
        AutoScaleDimensions = new SizeF(9f, 20f);
        AutoScaleMode = AutoScaleMode.Font;
        AutoScroll = true;
        ClientSize = new Size(344, 75);
        FormBorderStyle = FormBorderStyle.None;
        Margin = new Padding(3, 4, 3, 4);
        Name = "PluginView";
        ShowInTaskbar = false;
        StartPosition = FormStartPosition.Manual;
        Text = "Hot Plugging Host";
        ResumeLayout(false);
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing && components != null)
            components.Dispose();

        base.Dispose(disposing);
    }

    private void SetWidth()
    {
        if (_slots.Count > _maxVisibleslots)
        {
            Width = _dummy.Width + new VScrollBar().Width;
            HScroll = false;
            AutoScroll = true;
        }
        else
        {
            Width = _dummy.Width;
            AutoScroll = false;
        }
    }

    protected override CreateParams CreateParams
    {
        get
        {
            var createParams = base.CreateParams;
            createParams.ExStyle |= 128;
            return createParams;
        }
    }

    public PluginView()
    {
        InitializeComponent();
        _maxVisibleslots = (int)Math.Floor((Screen.GetWorkingArea(this).Height - 212) / (double)_dummy.Height);
        Visible = false;
    }

    public void ExtensionCreated(object source, ExtensionEventArgs e)
    {
        if (_slots.ContainsKey(e.ExtensionInfo))
            _slots[e.ExtensionInfo].AddRef();
        else
        {
            var slotButton = new SlotButton(e.ExtensionInfo);

            if (Controls.Count > 0)
            {
                var control = Controls[Controls.Count - 1];
                slotButton.Location = new Point(0, control.Location.Y + _dummy.Height);
            }

            Controls.Add(slotButton);
            _slots.Add(e.ExtensionInfo, slotButton);
            
            if (_slots.Count > 1 && _slots.Count <= _maxVisibleslots)
            {
                var pluginView = this;
                var height = pluginView.Height + _dummy.Height;
                pluginView.Height = height;
            }

            Visible = _slots.Count > 0;
            SetWidth();
            Update();
        }
    }

    public void ExtensionReleased(object source, ExtensionEventArgs e)
    {
        if (!Visible || !_slots.ContainsKey(e.ExtensionInfo) || !_slots[e.ExtensionInfo].Release())
            return;

        UserControl userControl = _slots[e.ExtensionInfo];
        userControl.Visible = false;

        var index = Controls.IndexOf(userControl);
        Controls.Remove(userControl);
        _slots.Remove(e.ExtensionInfo);

        for ( ; index < Controls.Count; ++index)
        {
            var control = Controls[index];
            control.Location = new Point(0, control.Location.Y - _dummy.Height);
        }

        if (_slots.Count > 0 && _slots.Count < _maxVisibleslots)
        {
            var pluginView = this;
            var hright = pluginView.Height - _dummy.Height;
            pluginView.Height = hright;
        }

        Visible = _slots.Count > 0;
        SetWidth();
        Update();
    }

}

